package com.bolt.admin.web.controller;

import com.alibaba.fastjson.JSON;
import com.bolt.admin.common.base.SimpleController;
import com.bolt.admin.module.sys.entity.TableConfig;
import com.bolt.admin.module.sys.entity.TableHeadConfig;
import com.bolt.admin.module.sys.service.CodeGeneratorService;
import com.bolt.admin.module.sys.service.TableConfigService;
import com.bolt.admin.module.sys.service.TableHeadConfigService;
import com.bolt.common.bean.BeanUtil;
import com.bolt.common.collection.MapUtil;
import com.bolt.common.utils.StrUtil;
import com.bolt.convention.data.ResultMessage;
import com.bolt.convention.data.Results;
import com.bolt.convention.data.Returns;
import com.bolt.core.view.components.Form;
import com.bolt.core.view.components.FormItem;
import com.bolt.core.view.config.PageRepository;
import com.bolt.support.codegenerator.model.Column;
import com.bolt.support.codegenerator.model.Table;
import com.bolt.support.spring.jpa.filter.FilterBuilder;
import com.bolt.support.spring.jpa.filter.GroupPropertyFilter;
import com.bolt.support.spring.mvc.annotation.ModelEntity;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 代码生成
 *
 * @author michao
 *         Created by Administrator on 2018/2/2.
 */
@Controller
@RequestMapping("/admin/sys/code_generator")
public class CodeGeneratorController extends SimpleController {

    @Autowired
    private CodeGeneratorService sourceCodeBuilder;

    @Autowired
    private PageRepository pageRepository;

    @Autowired
    private TableConfigService tableConfigService;

    @Autowired
    private TableHeadConfigService tableHeadConfigService;

    @Value("${project.src.dir}")
    private String rootDir;
    /**
     * 模块首页
     */
    @RequestMapping(value = "", method = RequestMethod.GET)
    public ModelAndView index(Model model, HttpServletRequest request) {
        return super.index("/admin/sys/code_generator/index", request, model.asMap());
    }

    /**
     * 代码生成
     *
     * @return
     */
    @RequestMapping(value = "codeGenerator", method = RequestMethod.GET)
    public ModelAndView codeGenerator(Model model, HttpServletRequest request) {
        return super.index("/admin/sys/code_generator/index-code-generator", request, model.asMap());
    }

    /**
     * 列表生成
     *
     * @return
     */
    @RequestMapping(value = "tableGenerator", method = RequestMethod.GET)
    public ModelAndView tableGenerator(Model model, HttpServletRequest request) {
        return super.index("/admin/sys/code_generator/index-table-generator", request, model.asMap());
    }


    /**
     * 读取数据库所有表信息
     *
     * @return
     */
    @RequestMapping(value = "getAllTables", method = RequestMethod.POST)
    @ResponseBody
    public ResultMessage getAllTables() {
        try {
            Map <String, String> tables = sourceCodeBuilder.getAllTables();
            return Returns.success(tables);
        } catch (Exception ex) {
            return Returns.error("表信息读取失败");
        }
    }


    /**
     * 表单成生
     *
     * @return
     */
    @RequestMapping(value = "formGenerator", method = RequestMethod.GET)
    public ModelAndView formGenerator(Model model, HttpServletRequest request) {

        return super.index("/admin/sys/code_generator/index-form-generator", request, model.asMap());
    }


    /**
     * 生成实体类代码
     *
     * @return
     */
    @RequestMapping(value = "codeGenerator", method = RequestMethod.POST)
    @ResponseBody
    public ResultMessage codeGenerator(String tableName) {

        Table table = sourceCodeBuilder.getTable(tableName);
        String entityCode = sourceCodeBuilder.generatorJavaCode(table,"/Entity.ftl");
        String controllerCode = sourceCodeBuilder.generatorJavaCode(table,"/Controller.ftl");
        String serviceCode = sourceCodeBuilder.generatorJavaCode(table,"/Service.ftl");
        String repositoryCode = sourceCodeBuilder.generatorJavaCode(table,"/Repository.ftl");

        String converterCode = sourceCodeBuilder.generatorJavaCode(table,"/Converter.ftl");
        String dtoCode = sourceCodeBuilder.generatorJavaCode(table,"/Dto.ftl");

        Map <String, Object> data = MapUtil.newHashMap();
        data.put("entityCode", entityCode);
        data.put("controllerCode", controllerCode);
        data.put("serviceCode", serviceCode);
        data.put("repositoryCode", repositoryCode);

        data.put("converterCode", converterCode);
        data.put("dtoCode", dtoCode);

        data.put("className", table.getClassName());
        return Returns.success(data);

    }

    @RequestMapping(value = "readFormConfig", method = RequestMethod.POST)
    @ResponseBody
    public ResultMessage readFormConfig(String modulePath) {
        String formCode = sourceCodeBuilder.readFormConfig(modulePath);
        return Returns.success().put(formCode);
    }

    /**
     * 生成实体类代码
     *
     * @return
     */
    @RequestMapping(value = "importSource", method = RequestMethod.POST)
    @ResponseBody
    public ResultMessage importSource(String basePackage,
                                      Long moduleId,
                                      String className,
                                      String path,
                                      String entityCode,
                                      String controllerCode,
                                      String repositoryCode,
                                      String serviceCode,
                                      String dtoCode,
                                      String converterCode) {


        if (StrUtil.isNotBlank(entityCode)) {
            sourceCodeBuilder.generatorCodeFile(basePackage, moduleId, path,"entity", className + ".java", entityCode);
        }
        if (StrUtil.isNotBlank(controllerCode)) {
            sourceCodeBuilder.generatorCodeFile(basePackage, moduleId, path,"controller", className + "Controller.java", controllerCode);
        }
        if (StrUtil.isNotBlank(repositoryCode)) {
            sourceCodeBuilder.generatorCodeFile(basePackage, moduleId, path,"repository", className + "Repository.java", repositoryCode);
        }
        if (StrUtil.isNotBlank(serviceCode)) {
            sourceCodeBuilder.generatorCodeFile(basePackage, moduleId, path,"service", className + "Service.java", serviceCode);
        }
        if (StrUtil.isNotBlank(dtoCode)) {
            sourceCodeBuilder.generatorCodeFile(basePackage, moduleId, path,"dto", className + "DTO.java", dtoCode);
        }
        if (StrUtil.isNotBlank(converterCode)) {
            sourceCodeBuilder.generatorCodeFile(basePackage, moduleId, path,"dto/converter", className + "Converter.java", converterCode);
        }
        return Returns.success("生成完成");


    }

    /**
     * 表单配置
     *
     * @return
     */
    @RequestMapping(value = "indexConfigForm", method = RequestMethod.GET)
    public String openIndexConfigForm(Model model, HttpServletRequest request) {
        return "/admin/sys/code_generator/index_config_form";
    }

    /**
     * @return
     */
    @RequestMapping(value = "generatorFormConfig", method = RequestMethod.GET)
    public String generatorFormConfig(Model model) {
        model.addAttribute("selectData", sourceCodeBuilder.loopAllEntityPackage());
        return "/admin/sys/code_generator/generator_form_config";
    }


    /**
     * 生成模块首页
     *
     * @param modulePath
     * @param dbGridId
     * @return
     */
    @RequestMapping(value = "importIndex", method = RequestMethod.POST)
    @ResponseBody
    public ResultMessage importIndex(String modulePath, String dbGridId, String moduleTitle) {
        if (StrUtil.isNotBlank(modulePath)) {
            sourceCodeBuilder.generatorIndexFile(modulePath, moduleTitle, dbGridId);
        } else {
            return Returns.error("请选择择模块");
        }
        return Returns.success("生成完成");
    }

    /**
     * 查出表单配置元素信息
     *
     * @param tableName
     * @return
     */
    @RequestMapping(value = "findTableForForm", method = RequestMethod.POST)
    @ResponseBody
    public List <Map <String, Object>> findTableForForm(String tableName) {
        List <Map <String, Object>> formData = new ArrayList <>();
        if (StrUtil.isNotBlank(tableName)) {
            Table table = sourceCodeBuilder.getTable(tableName);
            for (Column column : table.getColumns()) {
                if (column.getSqlName().equalsIgnoreCase("id") || column.getSqlName().equalsIgnoreCase("version_no")) {
                    continue;
                }
                Map <String, Object> data = new HashMap <>();
                data.put("label", column.getRemarks());
                data.put("id", column.getJavaProperty());
                data.put("type", "text");
                data.put("queryField", false);
                formData.add(data);
            }
        }
        return formData;
    }

    /**
     * 生成表单代码
     *
     * @param modulePath
     * @param moduleTitle
     * @param formItems
     * @return
     */
    @RequestMapping(value = "formGenerator", method = RequestMethod.POST)
    @ResponseBody
    public ResultMessage formGenerator(String modulePath, String moduleTitle, String formItems) {
        List <FormItem> data = JSON.parseArray(formItems, FormItem.class);
        String formCode = sourceCodeBuilder.generatorForm(modulePath, moduleTitle, data);
        return Returns.success().put(formCode);
    }

    /**
     * 生成表单配置文件
     *
     * @param modulePath
     * @param code
     * @return
     */
    @RequestMapping(value = "generatorFormFile", method = RequestMethod.POST)
    @ResponseBody
    public ResultMessage generatorFormFile(String modulePath, String code) {
        sourceCodeBuilder.generatorFormFile(modulePath, code);
        return Returns.success("生成成功");
    }

    /**
     * 刷新重载表单配置
     *
     * @param modulePath
     * @return
     */
    @RequestMapping(value = "reloadFormConfig", method = RequestMethod.POST)
    @ResponseBody
    public ResultMessage reloadFormConfig(String modulePath) {
        pageRepository.parse(modulePath);
        return Returns.success("刷新成功");

    }

    /**
     * 从项目文件中取有实体类名称
     *
     * @param packageName 包表
     * @return
     */
    @RequestMapping(value = "getEntityName", method = RequestMethod.POST)
    @ResponseBody
    public ResultMessage getEntityName(String packageName) {
        List <String[]> result = new ArrayList <>();
        List <String> entityNames = sourceCodeBuilder.filterAllEntityName(packageName);
        for (String name : entityNames) {
            String[] values = new String[2];
            values[0] = name;
            values[1] = name;
            result.add(values);
        }
        return Results.success(result);
    }

    /**
     * 取出所列表表头配置信息用于前台展示
     * @return
     */
    @RequestMapping(value = "dbTableList", method = RequestMethod.POST)
    @ResponseBody
    public ResultMessage list() {
        List <TableConfig> data = tableConfigService.findAll();
        return Returns.success(data);
    }


    /**
     * 列表配置编辑页
     *
     * @return
     */
    @RequestMapping(value = "editTable", method = RequestMethod.GET)
    public ModelAndView edit(@ModelEntity(value = Form.PAGECONTEXT_FORMVALUES) TableConfig tableConfig,ModelAndView model) {
        model.addObject("pagePath", "code_generator");
        model.addObject("formId", "table_config_form");
        model.setViewName("/admin/sys/code_generator/editTable-index");
        return model;
    }

    /**
     * 列表配置新增操作
     *
     * @param entity 表单数据
     * @return
     */
    @RequestMapping(value = "saveOrUpdateTableConfig", method = RequestMethod.POST)
    @ResponseBody
    public ResultMessage saveOrUpdate(TableConfig entity) {
        tableConfigService.save(entity);
        return Returns.success("编辑成功");
    }

    /**
     * 列表配置删除操作
     *
     * @param id 菜单ID
     * @return
     */
    @RequestMapping(value = "delTableConfig", method = RequestMethod.GET)
    @ResponseBody
    public ResultMessage doDeleteTableConfig(@RequestParam("id") String id) {
        if (StrUtil.isNotEmpty(id)) {
            tableConfigService.deleteById(id);
            return Returns.success("删除成功");
        } else {
            return Returns.warning("所有选取记录删除操作失败");
        }
    }

    /**
     * 打开导入表配置表单
     *
     * @param model
     * @return
     */
    @RequestMapping(value = "openImpTable", method = RequestMethod.GET)
    public ModelAndView openImpTableForm(ModelAndView model) {
        model.addObject("pagePath", "code_generator");
        model.addObject("formId", "table_import_form");
        model.setViewName("/admin/sys/code_generator/editTable-index");
        return model;
    }

    /**
     * 将表列导入系统配置用于列表显示
     *
     * @param tableName 表名
     * @return
     */
    @RequestMapping("impTable")
    @ResponseBody
    public ResultMessage impTable(String tableName) {

        Table table = sourceCodeBuilder.getTable(tableName);
        List <Column> columns = table.getColumns();
        String tableId = table.getSqlName() + "_table";
        List <TableHeadConfig> heads = new ArrayList <>();
        TableConfig tableConfig = new TableConfig();
        tableConfig.setTableId(tableId);
        tableConfig.setTableTitle(table.getRemarks());
        for (Column column : columns) {
            TableHeadConfig tableHead = new TableHeadConfig();
            tableHead.setField(column.getJavaProperty());
            tableHead.setTitle(StrUtil.subPre(column.getRemarks(), 50));//只取前50个
            tableHead.setAlign("center");
            tableHead.setWidth(80);
            tableHead.setOrderRank(10);
            tableHead.setHidden(false);
            heads.add(tableHead);
        }
        tableConfig.setTableHeads(heads);
        tableConfigService.save(tableConfig);
        return Returns.success("导入完成");


    }

    /**
     * 打开复制表格表单
     *
     * @param model
     * @return
     */
    @RequestMapping(value = "copyTable", method = RequestMethod.GET)
    public ModelAndView copyTable(ModelAndView model) {
        model.addObject("pagePath", "code_generator");
        model.addObject("formId", "copy_table_config_form");
        model.setViewName("/admin/sys/code_generator/editTable-index");
        return model;
    }

    /**
     * 复制 表格配置
     *
     * @param id
     * @param tableId
     * @return
     */
    @RequestMapping("doCopy")
    public ResultMessage doCopy(String id, String tableId) {
        TableConfig newConfig = new TableConfig();
        newConfig.setTableId(tableId);
        TableConfig tableConfig = tableConfigService.findOne(id).get();
        BeanUtil.copyProperties(tableConfig, newConfig, new String[]{"tableId", "id", "tableHeadConfig"});
        List <TableHeadConfig> heads = new ArrayList <>();
        for (TableHeadConfig tableHeadconfig : tableConfig.getTableHeads()) {
            TableHeadConfig newTableHead = new TableHeadConfig();
            newTableHead.setTableId(tableId);
            BeanUtil.copyProperties(tableHeadconfig, newTableHead, new String[]{"tableId", "id"});
            heads.add(newTableHead);
        }
        newConfig.setTableHeads(heads);

        tableConfigService.save(newConfig);
        return Returns.success("复制完成");

    }

    /**
     * @param model
     * @return
     */
    @RequestMapping(value = "createTableHead", method = RequestMethod.GET)
    public ModelAndView create(ModelAndView model) {
        model.addObject("pagePath", "code_generator");
        model.addObject("formId", "table_head_config_form");
        model.setViewName("/admin/sys/code_generator/editTable-index");
        return model;
    }

    /**
     * 列表配置编辑页
     *
     * @param entity 菜单ID
     * @param model
     * @return
     */
    @RequestMapping(value = "editTableHead", method = RequestMethod.GET)
    public String editHead(@ModelEntity(Form.PAGECONTEXT_FORMVALUES) TableHeadConfig entity, Model model) {
        model.addAttribute("pagePath", "code_generator");
        model.addAttribute("formId", "table_head_config_form");
        return "/admin/sys/code_generator/editTable-index";
    }

    /**
     * 列表配置新增操作
     *
     * @param entity 表单数据
     * @return
     */
    @RequestMapping(value = "saveOrUpdateTableHead", method = RequestMethod.POST)
    @ResponseBody
    public ResultMessage saveOrUpdate(TableHeadConfig entity) {
        tableHeadConfigService.save(entity);
        return Returns.success("编辑成功");
    }

    /**
     * 列表配置删除操作
     *
     * @param id 菜单ID
     * @return
     */
    @RequestMapping(value = "delTableHead", method = RequestMethod.GET)
    @ResponseBody
    public ResultMessage doDelete(@RequestParam("id") String id) {
        if (StrUtil.isNotEmpty(id)) {
            tableHeadConfigService.deleteById(id);
            return Returns.success("删除成功");
        } else {
            return Returns.warning("所有选取记录删除操作失败");
        }
    }

    @RequestMapping(value = "editTableHeads", method = RequestMethod.POST, headers = {"Content-type=application/json"})
    public ResultMessage saveForListTableHead(@RequestBody List <TableHeadConfig> datas) {
        try {
            tableHeadConfigService.save(datas);
            return Returns.success();
        } catch (Exception ex) {
            return Returns.error(ex.getMessage());

        }
    }

    /**
     * 查询列信息
     *
     * @param tableId
     * @return
     */
    @RequestMapping("findHeads")
    @ResponseBody
    public ResultMessage findTableHeads(String tableId) {
        GroupPropertyFilter filter = new  FilterBuilder<TableHeadConfig>()
                .lambda()
                .eq(TableHeadConfig::getTableId,tableId)
                .orderByAsc(TableHeadConfig::getOrderRank).build();
        List <TableHeadConfig> tableConfig = tableHeadConfigService.findAll(filter);
        return Returns.success(tableConfig);
    }

    /**
     * 序号重排
     *
     * @param ids
     * @return
     */
    @RequestMapping("reorder")
    @ResponseBody
    public ResultMessage reorder(String[] ids) {
        try {
            tableHeadConfigService.reorder(ids);
            return Returns.success("重排成功");
        } catch (Exception ex) {
            return Results.error(ex);
        }
    }
}
